/*********************************************************************
 *  Nome : Bruno Ferrero                             N.USP 3690142
 *  Nome : Mariana Pacheco Hatamura                  N.USP 4906967 
 *  Nome : Tiago Nicolosi Bomventi                   N.USP 3690177 
 *  Curso: BCC                                 Disciplina: MAC 211
 *  Data : 5/5/2010                       Exercic. Projeto(parte 1)
 *  Compilador utilizado : gcc versao 4.1.2
 *  ******************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "oceano.h"
#include "item.h"
#include "fisica.h"

static char oceano[OC_SIZE_X][OC_SIZE_Y];     /*matriz usada para desenhar na tela*/
static int naufragosNovos = 0;                /*naufragos gerados depois do inicio do jogo*/
static float freqGeraPassageiro;              /*frequencia com que os naufragos sao gerados*/
static float mediaDaVelocidadeGerada;         /*velocidade media dos naufragos gerados*/
static float desvioDaVelocidadeGerada;        /*desvio padrao da velocidade media*/

/*limpa todo o oceano*/
void limpaOceano (void) {
    int i, j;
    for (i = 0; i < OC_SIZE_X; i++)
        for (j = 0; j < OC_SIZE_Y; j++)
            oceano[i][j] = AGUA;
}

/*imprime todo o oceano*/
void imprimeOceano (void) {
    int i, j;
    printf ("Numero de naufragos no vetor = %d, numero de naufragos contados na matriz = %d, numero maximo de naufragos permitidos = %d\n", numNaufragosNoVetor(), contaNaufragos(), MAX_NAUFRAGOS);
    printf("(0,0)\n");
    for (i = 0; i < OC_SIZE_X; i++) {
        printf("     ");
        for (j = 0; j < OC_SIZE_Y; j++) 
            if (oceano[i][j] == AGUA)
                putchar (AGUA);
            else if (oceano[i][j] == CORAL)
                putchar (CORAL);
            else if (oceano[i][j] == NAUFRAGO)
                putchar (NAUFRAGO);
            else if (oceano[i][j] == COLISAO)
                putchar (COLISAO);
        printf ("\n");
    }
    for (j = 0; j < OC_SIZE_Y; j++) 
        printf(" ");
    printf("     (%d,%d)\n", OC_SIZE_X - 1, OC_SIZE_Y - 1);
}

/* preenche os tipos de objetos no oceano */
void atualizaOceano (int lin, int col, char tipo) {
    oceano[lin][col] = tipo;
}

/* devolve o tipo de objeto na posicao (lin, col) do oceano */
char tipoObjeto (int lin, int col) {
    return oceano [lin][col];
}

/*povoa o oceano com corais em posicoes aleatorias*/
void populaCoral (int quantidade) {
    int lin, col, i;
    for (i = 0 ; i < quantidade ; i++) {
        lin = rand() % OC_SIZE_X;
        col = rand() % OC_SIZE_Y;
        while (tipoObjeto(lin, col) != AGUA) {
            lin = rand() % OC_SIZE_X;
            col = rand() % OC_SIZE_Y;
        }
        atualizaOceano (lin, col, CORAL);
    }
}

/*povoa o oceano com naufragos em posicao aleatorias*/
void populaNaufragos (int quantidade) {
    int lin, col, i;
    float vx, vy;
    for (i = 0 ; i < quantidade ; i++) {
        sorteiaVelocidade (&vx, &vy);
        lin = rand() % OC_SIZE_X;
        col = rand() % OC_SIZE_Y;
        while (tipoObjeto (lin, col) != AGUA) {
            lin = rand() % OC_SIZE_X;
            col = rand() % OC_SIZE_Y;
        }
        if (numNaufragosNoVetor () >= MAX_NAUFRAGOS) break;
        criaNaufrago ((float)lin, (float)col, vx, vy);
        atualizaOceano (lin, col, NAUFRAGO);
    }
}

/*povoa o oceano com naufragos posicionados na borda*/
void geraNaufragosBorda (int quantidade) {
    int lin, col, i;
    float vx, vy;
    for (i = 0 ; i < quantidade ; i++) {
        sorteiaVelocidade (&vx, &vy);
        sorteiaBordas (&lin, &col);
        while (tipoObjeto (lin, col) != AGUA)
            sorteiaBordas (&lin, &col);
        if (numNaufragosNoVetor() >= MAX_NAUFRAGOS) break;
        printf("gerado naufrago em (%d, %d)\n", lin, col);
        criaNaufrago ((float)lin, (float)col, vx, vy);
        atualizaOceano (lin, col, NAUFRAGO);
    }
}

/*retorna um valor de bordas aleatorio para as variaveis borda1 e borda2*/
void sorteiaBordas (int *borda1, int *borda2) {
    int sorteio;
    sorteio = rand() % 4;
    if (sorteio == 0) {
        *borda1 = 0;
        *borda2 = rand() % OC_SIZE_Y;
    }
    else if (sorteio == 1) {
        *borda1 = OC_SIZE_X - 1;
        *borda2 = rand() % OC_SIZE_Y;
    }
    else if (sorteio == 2) {
        *borda1 = rand() % OC_SIZE_X;
        *borda2 = OC_SIZE_Y - 1;
    }
    else if (sorteio == 3) {
        *borda1 = rand() % OC_SIZE_X; 
        *borda2 = 0;
    }
}

/*sorteia um vetor velocidade com distribuicao ????uniforme?????*/
void sorteiaVelocidade (float *vx, float *vy) {
    int sorteio;
    float dir, vel=VELMAX + 1;
    sorteio = rand() % 8;
    if (sorteio == 0) 
        dir = NORTE;
    else if (sorteio == 1) 
        dir = NORDESTE;
    else if (sorteio == 2) 
        dir = LESTE;
    else if (sorteio == 3) 
        dir = SUDESTE;
    else if (sorteio == 4) 
        dir = SUL;
    else if (sorteio == 5) 
        dir = SUDOESTE;
    else if (sorteio == 6) 
        dir = OESTE;
    else if (sorteio == 7)
        dir = NOROESTE;
    while(vel > VELMAX)
        vel = gauss();   
    if (vel < 0) vel = -vel;
    polarParaEuclidiano (dir, vel, vx, vy);
    limiteVelocidade (vx, vy);
}

/*conta o numero de naufragos marcados na matriz oceano (finalidade de teste)*/
int contaNaufragos () {
    int i, j, cont;
    cont = 0;
    for (i = 0 ; i < OC_SIZE_X ; i++)
        for (j = 0 ; j < OC_SIZE_Y ; j++)
            if (oceano[i][j] == NAUFRAGO || oceano[i][j] == COLISAO)
                cont++;
    return cont;
}

/*limpa as colisoes marcadas na matriz oceano*/
int limpaColisoes (void) {
    int i, j, cont;
    cont = 0;
    for (i = 0 ; i < OC_SIZE_X ; i++) {
        for (j = 0 ; j < OC_SIZE_Y ; j++)
            if (oceano[i][j] == COLISAO) {
                oceano[i][j] = NAUFRAGO;
                cont++;
            }
    }
    return cont;
}

/*devolve o numero de naufragos criados apartir do primeiro instante do jogo
  Nao leva em consideracao os naufragos criados antes da primeira iteracao*/
int numNaufragosNovos (void) {
    return naufragosNovos;
}

/*frequencia com que os naufragos sao gerados por unidade de tempo*/
void frequenciaGeracaoNaufrago (void) {
    int chance;
    int naufragosGerados;        
    if (freqGeraPassageiro < 1.0) {
        chance = (int) (freqGeraPassageiro * 100);
        if (rand() % 100 < chance) {
            geraNaufragosBorda (1);
            naufragosNovos++;
        } 
    }
    else {
        naufragosGerados = (int) (freqGeraPassageiro * 2) + 0.5;
        while (naufragosGerados > 0) {
            if (rand() % 100 < 50) {
                geraNaufragosBorda(1);
                naufragosNovos++;
            }
            naufragosGerados--;
        }
    }
}

/*distribuicao uniforme entre 0 e 1*/
float uniform(void)    
{   
    float t;   
    t = (float) rand()/RAND_MAX;   
    return(t);   
}   

/*distribuicao de gauss (obtido da internet)*/
float gauss(void)   
{   int i;   
    float x,y;   
    for(x=0,i=0;i<12;i++)   
    {x=x+uniform();}
    x=x-6.0;   
    y=mediaDaVelocidadeGerada+x*desvioDaVelocidadeGerada;   
    return(y);   
}   

/*define a frequencia de passageiros*/
void setFreqGeraPassageiro(float freq){
    freqGeraPassageiro = freq;
}

/*define a media e o desvio padrao da distribuicao usada para gerar o vetor velocidade*/
void setMediaDaVelocidadeGerada(float media, float desvio){
    mediaDaVelocidadeGerada = media;
    desvioDaVelocidadeGerada = desvio;
}

/* funcao que limpa a tela */
int limpaJanela (void)
{
    printf("\033[2J");
    printf("\033[0;0f");
    return (0);
}
